---
title: "Reference: MCPClient | Tool Management | Kastrax Docs"
description: API Reference for MCPClient - A class for managing multiple Model Context Protocol servers and their tools.
---

# MCPClient ✅

The `MCPClient` class provides a way to manage multiple MCP server connections and their tools in a Kastrax application. It handles connection lifecycle, tool namespacing, and provides convenient access to tools across all configured servers.

## Constructor ✅

Creates a new instance of the MCPClient class.

```typescript
constructor({
  id?: string;
  servers: Record<string, KastraxMCPServerDefinition>;
  timeout?: number;
}: MCPClientOptions)
```

### MCPClientOptions

<br />
<PropertiesTable
  content={[
    {
      name: "id",
      type: "string",
      isOptional: true,
      description:
        "Optional unique identifier for the configuration instance. Use this to prevent memory leaks when creating multiple instances with identical configurations.",
    },
    {
      name: "servers",
      type: "Record<string, KastraxMCPServerDefinition>",
      description:
        "A map of server configurations, where each key is a unique server identifier and the value is the server configuration.",
    },
    {
      name: "timeout",
      type: "number",
      isOptional: true,
      defaultValue: "60000",
      description: "Global timeout value in milliseconds for all servers unless overridden in individual server configs.",
    },
  ]}
/>

### KastraxMCPServerDefinition

Each server in the `servers` map is configured using the `KastraxMCPServerDefinition` type. The `KastraxMCPClient` used internally automatically detects the transport type based on the provided parameters:

-   If `command` is provided, it uses the Stdio transport.
-   If `url` is provided, it first attempts to use the Streamable HTTP transport and falls back to the legacy SSE transport if the initial connection fails.

<br />
<PropertiesTable
  content={[
    {
      name: "command",
      type: "string",
      isOptional: true,
      description: "For Stdio servers: The command to execute.",
    },
    {
      name: "args",
      type: "string[]",
      isOptional: true,
      description: "For Stdio servers: Arguments to pass to the command.",
    },
    {
      name: "env",
      type: "Record<string, string>",
      isOptional: true,
      description: "For Stdio servers: Environment variables to set for the command.",
    },
    {
      name: "url",
      type: "URL",
      isOptional: true,
      description: "For HTTP servers (Streamable HTTP or SSE): The URL of the server.",
    },
    {
      name: "requestInit",
      type: "RequestInit",
      isOptional: true,
      description: "For HTTP servers: Request configuration for the fetch API.",
    },
    {
      name: "eventSourceInit",
      type: "EventSourceInit",
      isOptional: true,
      description: "For SSE fallback: Custom fetch configuration for SSE connections. Required when using custom headers with SSE.",
    },
    {
      name: "logger",
      type: "LogHandler",
      isOptional: true,
      description: "Optional additional handler for logging.",
    },
    {
      name: "timeout",
      type: "number",
      isOptional: true,
      description: "Server-specific timeout in milliseconds.",
    },
    {
      name: "capabilities",
      type: "ClientCapabilities",
      isOptional: true,
      description: "Server-specific capabilities configuration.",
    },
    {
      name: "enableServerLogs",
      type: "boolean",
      isOptional: true,
      defaultValue: "true",
      description: "Whether to enable logging for this server.",
    },
  ]}
/>

## Methods ✅

### getTools()

Retrieves all tools from all configured servers, with tool names namespaced by their server name (in the format `serverName_toolName`) to prevent conflicts.
Intended to be passed onto an Agent definition.

```ts
new Agent({ tools: await mcp.getTools() });
```

### getToolsets()

Returns an object mapping namespaced tool names (in the format `serverName.toolName`) to their tool implementations.
Intended to be passed dynamically into the generate or stream method.

```typescript
const res = await agent.stream(prompt, {
  toolsets: await mcp.getToolsets(),
});
```

### disconnect()

Disconnects from all MCP servers and cleans up resources.

```typescript
async disconnect(): Promise<void>
```

## Examples ✅

### Basic Usage

```typescript
import { MCPClient } from "@kastrax/mcp";
import { Agent } from "@kastrax/core/agent";
import { openai } from "@ai-sdk/openai";

const mcp = new MCPClient({
  servers: {
    stockPrice: {
      command: "npx",
      args: ["tsx", "stock-price.ts"],
      env: {
        API_KEY: "your-api-key",
      },
      log: (logMessage) => {
        console.log(`[${logMessage.level}] ${logMessage.message}`);
      },
    },
    weather: {
      url: new URL("http://localhost:8080/sse"),∂
    },
  },
  timeout: 30000, // Global 30s timeout
});

// Create an agent with access to all tools
const agent = new Agent({
  name: "Multi-tool Agent",
  instructions: "You have access to multiple tool servers.",
  model: openai("gpt-4"),
  tools: await mcp.getTools(),
});
```

### Using Toolsets in generate() or stream()

```typescript
import { Agent } from "@kastrax/core/agent";
import { MCPClient } from "@kastrax/mcp";
import { openai } from "@ai-sdk/openai";

// Create the agent first, without any tools
const agent = new Agent({
  name: "Multi-tool Agent",
  instructions: "You help users check stocks and weather.",
  model: openai("gpt-4"),
});

// Later, configure MCP with user-specific settings
const mcp = new MCPClient({
  servers: {
    stockPrice: {
      command: "npx",
      args: ["tsx", "stock-price.ts"],
      env: {
        API_KEY: "user-123-api-key",
      },
      timeout: 20000, // Server-specific timeout
    },
    weather: {
      url: new URL("http://localhost:8080/sse"),
      requestInit: {
        headers: {
          Authorization: `Bearer user-123-token`,
        },
      },
    },
  },
});

// Pass all toolsets to stream() or generate()
const response = await agent.stream(
  "How is AAPL doing and what is the weather?",
  {
    toolsets: await mcp.getToolsets(),
  },
);
```

## Resource Management ✅

The `MCPClient` class includes built-in memory leak prevention for managing multiple instances:

1. Creating multiple instances with identical configurations without an `id` will throw an error to prevent memory leaks
2. If you need multiple instances with identical configurations, provide a unique `id` for each instance
3. Call `await configuration.disconnect()` before recreating an instance with the same configuration
4. If you only need one instance, consider moving the configuration to a higher scope to avoid recreation

For example, if you try to create multiple instances with the same configuration without an `id`:

```typescript
// First instance - OK
const mcp1 = new MCPClient({
  servers: {
    /* ... */
  },
});

// Second instance with same config - Will throw an error
const mcp2 = new MCPClient({
  servers: {
    /* ... */
  },
});

// To fix, either:
// 1. Add unique IDs
const mcp3 = new MCPClient({
  id: "instance-1",
  servers: {
    /* ... */
  },
});

// 2. Or disconnect before recreating
await mcp1.disconnect();
const mcp4 = new MCPClient({
  servers: {
    /* ... */
  },
});
```

## Server Lifecycle ✅

MCPClient handles server connections gracefully:

1. Automatic connection management for multiple servers
2. Graceful server shutdown to prevent error messages during development
3. Proper cleanup of resources when disconnecting

## Related Information ✅

- For more about the Model Context Protocol, see the [@modelcontextprotocol/sdk documentation](https://github.com/modelcontextprotocol/typescript-sdk)
